package com.hy.common.config.exception;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.hy.common.Result.ResponseEnum;
import com.hy.common.exception.ExceptionResult;
import com.hy.common.exception.StandardException;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @作用 全局异常捕获
 * @作者 坏银
 * @时间 2022/4/14 11:30
 */
@RestControllerAdvice
public class GlobalRestExceptionHandler {
    /**
     * 对服务器出现RuntimeException进行捕获
     * 缺点：不明确
     */
    @ExceptionHandler(RuntimeException.class)
    public ExceptionResult makeExcepton(RuntimeException runtimeException) {
        runtimeException.printStackTrace();
        return ExceptionResult.fail(ResponseEnum.SERVER_ERROR, runtimeException);
    }

    /**
     * 对自定义常规异常的拦截
     */
    @ExceptionHandler(StandardException.class)
    public ExceptionResult makeException(StandardException standardException) {
        standardException.printStackTrace();
        return ExceptionResult.fail(standardException.getCode(), "StandardException", standardException.getMessage());
    }

    /**
     * 方法参数无效异常的处理
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ExceptionResult handlerValiator(MethodArgumentNotValidException e) throws JsonProcessingException {
        // 1: 从MethodArgumentNotValidException提取验证失败的所有的信息。返回一个List<FieldError>
        List<FieldError> fieldErrors = e.getBindingResult().getFieldErrors();
        // 2: 把fieldErrors中，需要的部分提出出来进行返回
        List<Map<String, String>> mapList = toValidatorMsg(fieldErrors);
        // 3: 把需要的异常信息转换成json进行返回
        ObjectMapper objectMapper = new ObjectMapper();
        String mapJson = objectMapper.writeValueAsString(mapList);
        ExceptionResult exceptionR = ExceptionResult.fail(ResponseEnum.SERVER_ERROR.getCode(), MethodArgumentNotValidException.class.getName(), mapJson);
        return exceptionR;
    }


    /**
     * 对验证异常进行统一处理提取需要的部分
     */
    private List<Map<String, String>> toValidatorMsg(List<FieldError> fieldErrorList) {
        List<Map<String, String>> mapList = new ArrayList<>();
        // 循环提取
        for (FieldError fieldError : fieldErrorList) {
            Map<String, String> map = new HashMap<>();
            // 获取验证失败的属性
            map.put("field", fieldError.getField());
            // 获取验证失败的的提示信息
            map.put("msg", fieldError.getDefaultMessage());

            mapList.add(map);
        }
        return mapList;
    }
}
